package com.epoch.base.db;

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;

import org.apache.commons.lang3.StringUtils;

/**
 * SQL语句处理工具类。<br>
 * 提供针对SQL语句进行自定义处理的工具方法，如模糊查询参数转义包装等操作。<br>
 * @author Royce Wang
 */
public class SqlUtils {
    /**
     * SQL模糊查询参数的包装方法，全模糊查询(包含指定参数，参数左右均通配任意字符)<br>
     * 调用此方法将传入的SQL查询参数包装成模糊查询所需的格式，对其中特殊字符会进行转义处理<br>
     * 如：<br>
     * <pre>
     * SqlUtils.fuzzy("foo_bar=5%"); // 返回结果字符串为"%foo/_bar=5/%%"
     * </pre>
     * @param param 模糊查询参数
     * @return 包装好格式的模糊查询参数
     */
    public static String fuzzy(String param) {
        String result = escapeFuzzy(param);
        if (StringUtils.isNotEmpty(result)) {
            result = "%" + result + "%";
        }
        return result;
    }

    /**
     * SQL模糊查询参数的包装方法，左模糊查询(以指定参数结尾，参数左侧通配任意字符)<br>
     * 调用此方法将传入的SQL查询参数包装成模糊查询所需的格式，对其中特殊字符会进行转义处理<br>
     * 如：<br>
     * <pre>
     * SqlUtils.fuzzyLeft("foo_bar=5%"); // 返回结果字符串为"%foo/_bar=5/%"
     * </pre>
     * @param param 模糊查询参数
     * @return 包装好格式的模糊查询参数
     */
    public static String fuzzyLeft(String param) {
        String result = escapeFuzzy(param);
        if (StringUtils.isNotEmpty(result)) {
            result = "%" + result;
        }
        return result;
    }

    /**
     * SQL模糊查询参数的包装方法，右模糊查询(以指定参数开头，参数右侧通配任意字符)<br>
     * 调用此方法将传入的SQL查询参数包装成模糊查询所需的格式，对其中特殊字符会进行转义处理<br>
     * 如：<br>
     * <pre>
     * SqlUtils.fuzzyRight("foo_bar=5%"); // 返回结果字符串为"foo/_bar=5/%%"
     * </pre>
     * @param param 模糊查询参数
     * @return 包装好格式的模糊查询参数
     */
    public static String fuzzyRight(String param) {
        String result = escapeFuzzy(param);
        if (StringUtils.isNotEmpty(result)) {
            result = result + "%";
        }
        return result;
    }

    /**
     * SQL模糊查询参数的包装方法，全模糊查询(包含指定参数，参数左右均通配任意字符)<br>
     * 调用此方法将传入的SQL查询参数Map中的所有字符串类型参数包装成模糊查询所需的格式，对其中特殊字符会进行转义处理<br>
     * 如：<br>
     * <pre>
     * Map<String,Object> params = new HashMap<String,Object>();
     * params.put("descn","foo_bar=5%");
     * params.put("age",Integer.valueOf(25));
     * Map<String,String> fuzzyParams = SqlUtils.fuzzy(params);
     * // 返回的fuzzyParams map中仅包含一个映射"descn":"%foo/_bar=5/%%"
     * </pre>
     * @param params 模糊查询参数map
     * @return 包装好格式的模糊查询参数map，其中仅包括所有包装过的字符串类型参数
     */
    public static Map<String, String> fuzzy(Map<String, Object> params) {
        Map<String, String> result = null;
        if (params != null) {
            result = new HashMap<String, String>();
            Iterator<Entry<String, Object>> it = params.entrySet().iterator();
            while (it.hasNext()) {
                Entry<String, Object> entry = it.next();
                Object val = entry.getValue();
                if (val instanceof String) {
                    result.put(entry.getKey(), fuzzy((String)val));
                }
            }
        }
        return result;
    }

    /**
     * SQL模糊查询参数的包装方法，左模糊查询(以指定参数结尾，参数左侧通配任意字符)<br>
     * 调用此方法将传入的SQL查询参数Map中的所有字符串类型参数包装成模糊查询所需的格式，对其中特殊字符会进行转义处理<br>
     * 如：<br>
     * <pre>
     * Map<String,Object> params = new HashMap<String,Object>();
     * params.put("descn","foo_bar=5%");
     * params.put("age",Integer.valueOf(25));
     * Map<String,String> fuzzyParams = SqlUtils.fuzzyLeft(params);
     * // 返回的fuzzyParams map中仅包含一个映射"descn":"%foo/_bar=5/%"
     * </pre>
     * @param params 模糊查询参数map
     * @return 包装好格式的模糊查询参数map，其中仅包括所有包装过的字符串类型参数
     */
    public static Map<String, String> fuzzyLeft(Map<String, Object> params) {
        Map<String, String> result = null;
        if (params != null) {
            result = new HashMap<String, String>();
            Iterator<Entry<String, Object>> it = params.entrySet().iterator();
            while (it.hasNext()) {
                Entry<String, Object> entry = it.next();
                Object val = entry.getValue();
                if (val instanceof String) {
                    result.put(entry.getKey(), fuzzy((String)val));
                }
            }
        }
        return result;
    }

    /**
     * SQL模糊查询参数的包装方法，右模糊查询(以指定参数开头，参数右侧通配任意字符)<br>
     * 调用此方法将传入的SQL查询参数Map中的所有字符串类型参数包装成模糊查询所需的格式，对其中特殊字符会进行转义处理<br>
     * 如：<br>
     * <pre>
     * Map<String,Object> params = new HashMap<String,Object>();
     * params.put("descn","foo_bar=5%");
     * params.put("age",Integer.valueOf(25));
     * Map<String,String> fuzzyParams = SqlUtils.fuzzyRight(params);
     * // 返回的fuzzyParams map中仅包含一个映射"descn":"foo/_bar=5/%%"
     * </pre>
     * @param params 模糊查询参数map
     * @return 包装好格式的模糊查询参数map，其中仅包括所有包装过的字符串类型参数
     */
    public static Map<String, String> fuzzyRight(Map<String, Object> params) {
        Map<String, String> result = null;
        if (params != null) {
            result = new HashMap<String, String>();
            Iterator<Entry<String, Object>> it = params.entrySet().iterator();
            while (it.hasNext()) {
                Entry<String, Object> entry = it.next();
                Object val = entry.getValue();
                if (val instanceof String) {
                    result.put(entry.getKey(), fuzzy((String)val));
                }
            }
        }
        return result;
    }

    /**
     * SQL模糊查询参数的转义方法<br>
     * 调用此方法将对传入的SQL查询参数中的特殊字符进行转义处理，转义符固定使用'/'<br>
     * 如：<br>
     * <pre>
     * SqlUtils.escapeFuzzy("foo_bar=5%"); // 返回结果字符串为"foo/_bar=5/%"
     * </pre>
     * @param str 模糊查询参数
     * @return 经过转义处理的模糊查询参数
     */
    public static String escapeFuzzy(String str) {
        String result = str;
        if (StringUtils.isNotEmpty(result)) {
            result = result.replace("/", "//");
            result = result.replace("%", "/%");
            result = result.replace("_", "/_");
        }
        return result;
    }

    private SqlUtils() {
        // 私有化构造方法，阻止工具类被实例化
    }
}
